#include "flight_system.h"

void print_menu(void)
{
    putchar('\n');
    int i;
    for (i = 0; i < 23; i++)
        printf("-");
    printf("\e[33m航班菜单\e[0m");
    for (i = 0; i < 22; i++)
        printf("-");
    putchar('\n');

    for (i = 0; i < 5; i++)
        printf("-");
    printf("1.增加航班");
    for (i = 0; i < 19; i++)
        printf("-");
    printf("2.浏览航班");
    for (i = 0; i < 9; i++)
        printf("-");
    putchar('\n');

    for (i = 0; i < 5; i++)
        printf("-");
    printf("3.修改航班信息");
    for (i = 0; i < 15; i++)
        printf("-");
    printf("4.删除航班信息");
    for (i = 0; i < 5; i++)
        printf("-");
    putchar('\n');

    for (i = 0; i < 5; i++)
        printf("-");
    printf("5.查询航班路线");
    for (i = 0; i < 15; i++)
        printf("-");
    printf("6.航班排序");
    for (i = 0; i < 9; i++)
        printf("-");
    putchar('\n');

    for (i = 0; i < 5; i++)
        printf("-");
    printf("7.购票");
    for (i = 0; i < 23; i++)
        printf("-");
    printf("8.退票");
    for (i = 0; i < 13; i++)
        printf("-");
    putchar('\n');

    for (i = 0; i < 5; i++)
        printf("-");
    printf("9.个人中心");
    for (i = 0; i < 19; i++)
        printf("-");
    printf("0.退出系统");
    for (i = 0; i < 9; i++)
        printf("-");
    putchar('\n');

    printf("请输入你要执行的操作(0~9):");
}

void print_file(FILE *fp)
{
    rewind(fp);
    char ch;
    while (!feof(fp))
    {
        ch = fgetc(fp);
        putchar(ch);
    }
}

void init_dlist(dList *dl)
{
    *dl = (dList)malloc(sizeof(dNode));
    (*dl)->next = NULL;
    (*dl)->fl = NULL;
}

void init_flist(fList *fl)
{
    *fl = (fList)malloc(sizeof(fNode));
    (*fl)->after = *fl;
    (*fl)->before = *fl;
}

void read_file_data(FILE *fp, dList dl)
{
    dNode *p = dl; // 尾天节点
    while (!feof(fp))
    {
        dNode *q = (dNode *)malloc(sizeof(dNode)); // 天节点
        q->next = NULL;
        init_flist(&q->fl);
        fscanf(fp, "%s\t%d趟航班\n", q->time, &q->n); // 读取日期和航班数量
        fNode *rear = q->fl;
        for (int j = 0; j < q->n; j++)
        {
            fNode *temp = (fNode *)malloc(sizeof(fNode));
            fscanf(fp, "%d\t%s\t%s\t", &temp->data.id, temp->data.flightName, temp->data.flightType);
            fscanf(fp, "%s\t%s\t%s\t", temp->data.startCity, temp->data.startTime, temp->data.arriveCity);
            fscanf(fp, "%s\t%s\t%d\t", temp->data.arriveTime, temp->data.flyTime, &temp->data.value);
            fscanf(fp, "%d\t%d\t%c\n", &temp->data.maxNum, &temp->data.leftTable, &temp->data.isFly);
            rear->after = temp;
            temp->before = rear;
            temp->after = q->fl;
            q->fl->before = temp;
            rear = temp;
        }
        p->next = q; // 连接天节点
        p = q;       // 尾节点
    }
}

void print_dlist(dList dl)
{
    dNode *p;
    p = dl->next;     // 天数据节点
    while (p != NULL) // 判断单链表尾部
    {
        printf("%s\t%d趟航班\n", p->time, p->n);
        fNode *q;
        q = p->fl->after; // 航班数据节点
        puts("班次\t航班名字\t机型\t起点\t起飞时间\t终点\t到达时间\t飞行时间\t票价\t载客量\t剩余票\t是否起飞");
        while (q != p->fl) // 判断到达循环双链表尾部
        {
            printf("%d\t%s\t%s\t", q->data.id, q->data.flightName, q->data.flightType);
            printf("%s\t%s\t\t%s\t", q->data.startCity, q->data.startTime, q->data.arriveCity);
            printf("%s\t\t%s\t$%d\t", q->data.arriveTime, q->data.flyTime, q->data.value);
            printf("%d\t%d\t%c\n", q->data.maxNum, q->data.leftTable, q->data.isFly);
            q = q->after;
        }
        p = p->next;
    }
}

void insert_flight(dList dl)
{
    printf("请输入你要增加航班的日期:");
    char time[MAX];
    scanf("%s", time);
    dNode *p = dl->next;
    while (p != NULL) // 循环遍历天链表
    {
        if (!strcmp(p->time, time)) // 找到对应的日期的天节点
        {
            printf("当天已有%d趟航班\n", p->n);
            fNode *rear = p->fl->before;               // 移动到航班循环链表尾部
            fNode *q = (fNode *)malloc(sizeof(fNode)); // 添加新节点
            printf("班次:");
            scanf("%d", &q->data.id);
            printf("航班名字:");
            scanf("%s", q->data.flightName);
            printf("机型:");
            scanf("%s", q->data.flightType);
            printf("起点:");
            scanf("%s", q->data.startCity);
            printf("起飞时间:");
            scanf("%s", q->data.startTime);
            printf("终点:");
            scanf("%s", q->data.arriveCity);
            printf("到达时间:");
            scanf("%s", q->data.arriveTime);
            printf("飞行时间:");
            scanf("%s", q->data.flyTime);
            printf("票价:$");
            scanf("%d", &q->data.value);
            printf("载客量:");
            scanf("%d", &q->data.maxNum);
            printf("剩余票:");
            scanf("%d", &q->data.leftTable);
            printf("是否起飞:");
            getchar(); // 吃回车
            scanf("%c", &q->data.isFly);
            rear->after = q;
            q->before = rear;
            q->after = p->fl;
            p->fl->before = q;
            p->n++;
            puts("航班增加成功");
            return;
        }
        p = p->next;
    }
    puts("\e[31m仅可添加当天和未来10天的航班!添加失败!\e[0m");
}

void change_flight(dList dl)
{
    printf("你要修改的航班的日期:");
    char time[MAX];
    scanf("%s", time);
    dNode *p = dl->next;
    while (p != NULL) // 循环遍历天链表
    {
        if (!strcmp(p->time, time)) // 找到对应的日期的天节点
        {
            printf("当天共有%d趟航班,请输入你要修改的班次(1~%d):", p->n, p->n);
            int id;
            scanf("%d", &id);
            while (id > p->n || id < 1) // 排除非法班次
            {
                printf("仅可修改1~%d的航班号,请重新输入:", p->n);
                scanf("%d", &id);
            }
            fNode *q = p->fl->after;
            while (q != p->fl) // 遍历航班班次
            {
                if (q->data.id == id) // 找到我们要修改的航班
                {
                    print_flight(q); // 打印
                    puts("1.班次\t\t2.航班名字\t3.机型\t\t4.起点");
                    puts("5.起飞时间\t6.终点\t\t7.到达时间\t8.飞行时间");
                    puts("9.票价\t\t10.载客量\t11.剩余票\t12.是否起飞");
                    printf("请输入你要修改的数据项(1~12):");
                    int num;
                    scanf("%d", &num);
                    switch (num)
                    {
                    case 1:
                        printf("修改后的班次:");
                        scanf("%d", &q->data.id);
                        break;
                    case 2:
                        printf("修改后的航班名字:");
                        scanf("%s", q->data.flightName);
                        break;
                    case 3:
                        printf("修改后的机型:");
                        scanf("%s", q->data.flightType);
                        break;
                    case 4:
                        printf("修改后的起点:");
                        scanf("%s", q->data.startCity);
                        break;
                    case 5:
                        printf("修改后的起飞时间:");
                        scanf("%s", q->data.startTime);
                        break;
                    case 6:
                        printf("修改后的终点:");
                        scanf("%s", q->data.arriveCity);
                        break;
                    case 7:
                        printf("修改后的到达时间:");
                        scanf("%s", q->data.arriveTime);
                        break;
                    case 8:
                        printf("修改后的飞行时间:");
                        scanf("%s", q->data.flyTime);
                        break;
                    case 9:
                        printf("修改后的票价:");
                        scanf("%d", &q->data.value);
                        break;
                    case 10:
                        printf("修改后的载客量:");
                        scanf("%d", &q->data.maxNum);
                        break;
                    case 11:
                        printf("修改后的剩余票:");
                        scanf("%d", &q->data.leftTable);
                        break;
                    case 12:
                        printf("修改后的是否起飞:");
                        getchar(); // 吃回车
                        scanf("%c", &q->data.isFly);
                    }
                    puts("\e[32m修改成功!\e[0m");
                    print_flight(q); // 打印修改后的航班；
                    return;
                }
                q = q->after;
            }
            puts("\e[31m当天没有这个班次的航班!\e[0m");
            return;
        }
        p = p->next;
    }
    puts("\e[31m仅可修改当天和未来10天的航班!修改失败!\e[0m");
    return;
}

void print_flight(fNode *fn)
{
    for (int i = 0; i < 50; i++)
        printf("-");
    printf("航班信息");
    for (int i = 0; i < 50; i++)
        printf("-");
    putchar('\n');
    printf("%d\t%s\t%s\t", fn->data.id, fn->data.flightName, fn->data.flightType);
    printf("%s\t%s\t%s\t", fn->data.startCity, fn->data.startTime, fn->data.arriveCity);
    printf("%s\t%s\t$%d\t", fn->data.arriveTime, fn->data.flyTime, fn->data.value);
    printf("%d\t%d\t%c\n", fn->data.maxNum, fn->data.leftTable, fn->data.isFly);
    putchar('\n');
}

void find_flight(dList dl)
{
    printf("请选择查询方式(1.按班次查询  2.按终点查询):");
    int num;
    scanf("%d", &num);
    if (num == 1) // 按班次查询
    {
        puts("按班次查询");
        printf("请输入你要查询航班的日期:");
        char time[MAX];
        scanf("%s", time);
        dNode *p = dl->next;
        while (p != NULL) // 循环遍历天链表
        {
            if (!strcmp(p->time, time)) // 找到对应的日期的天节点
            {
                printf("当天共有%d趟航班,请输入你要查询的班次(1~%d):", p->n, p->n);
                int id;
                scanf("%d", &id);
                while (id > p->n || id < 1) // 排除非法班次
                {
                    printf("仅可查询1~%d的航班号,请重新输入:", p->n);
                    scanf("%d", &id);
                }
                fNode *q = p->fl->after;
                while (q != p->fl) // 遍历航班班次
                {
                    if (q->data.id == id) // 找到我们要查询的航班
                    {
                        print_flight(q);
                        return;
                    }
                    q = q->after;
                }
            }
            p = p->next;
        }
        for (int i = 0; i < 10; i++)
            printf("*");
        printf("\e[31m你输入的日期无效!\e[0m"); // 没有找到日期
        for (int i = 0; i < 10; i++)
            printf("*");
        putchar('\n');
        return;
    }
    else
    {
        puts("按终点查询");
        printf("请输入你要查询的终点站名:");
        char arrivecity[MAX];
        scanf("%s", arrivecity);
        dNode *p = dl->next;
        int flag = 0; // 判断是否查找到
        putchar('\n');
        while (p != NULL)
        {
            fNode *q = p->fl->after;
            while (q != p->fl)
            {
                if (!strcmp(q->data.arriveCity, arrivecity))
                {
                    printf("%s\n", p->time);
                    print_flight(q);
                    flag = 1; // 查找到了
                }
                q = q->after; // 向下一个航班查询
            }
            p = p->next; // 向下一天查询
        }
        if (flag == 1)
            return;
        for (int i = 0; i < 10; i++)
            printf("*");
        printf("\e[31m未查询到以%s为终点站的航班\e[0m", arrivecity); // 没有找到这个终点站
        for (int i = 0; i < 10; i++)
            printf("*");
        putchar('\n');
        return;
    }
}

void delete_flight(dList dl)
{
    printf("请输入你要删除航班的日期:");
    char time[MAX];
    scanf("%s", time);
    dNode *p = dl->next;
    while (p != NULL) // 循环遍历天链表
    {
        if (!strcmp(p->time, time)) // 找到对应的日期的天节点
        {
            printf("当天共有%d趟航班,请输入你要删除的班次(1~%d):", p->n, p->n);
            int id;
            scanf("%d", &id);
            while (id > p->n || id < 1) // 排除非法班次
            {
                printf("仅可删除1~%d的航班号,请重新输入:", p->n);
                scanf("%d", &id);
            }
            fNode *q = p->fl->after;
            while (q != p->fl) // 遍历航班班次
            {
                if (q->data.id == id) // 找到我们要删除的航班
                {
                    fNode *pre = q->before; // 被删除节点的前驱
                    pre->after = q->after;
                    q->after->before = pre;
                    puts("\e[32m删除成功!\e[0m");
                    p->n--;
                    return;
                }
                q = q->after;
            }
        }
        p = p->next;
    }
    for (int i = 0; i < 10; i++)
        printf("*");
    printf("\e[31m你输入的日期无效!无法删除!\e[0m"); // 没有找到日期
    for (int i = 0; i < 10; i++)
        printf("*");
    putchar('\n');
    return;
}

void exit_system(void)
{
    system("clear"); // 清屏
    for (int i = 0; i < 10; i++)
        printf("*");
    printf("\e[32m已退出系统!欢迎下次光临!\e[0m");
    for (int i = 0; i < 10; i++)
        printf("*");
    putchar('\n');
}

void input_file(FILE *fp, dList dl)
{
    fflush(stdin);
    fflush(stdout);
    dNode *p = dl->next;
    while (p != NULL)
    {
        fprintf(fp, "%s\t%d趟航班\n", p->time, p->n);
        fNode *q = p->fl->after;
        while (q != p->fl)
        {
            fprintf(fp, "%d\t%s\t%s\t", q->data.id, q->data.flightName, q->data.flightType);
            fprintf(fp, "%s\t%s\t%s\t", q->data.startCity, q->data.startTime, q->data.arriveCity);
            fprintf(fp, "%s\t%s\t%d\t", q->data.arriveTime, q->data.flyTime, q->data.value);
            fprintf(fp, "%d\t%d\t%c\n", q->data.maxNum, q->data.leftTable, q->data.isFly);
            q = q->after;
        }
        p = p->next;
    }
}

void buy_ticket(dList dl, record *rl)
{
    printf("请输入你要购买的日期:");
    char time[MAX];
    scanf("%s", time);
    dNode *p = dl->next;
    while (p != NULL)
    {
        if (!strcmp(p->time, time))
        {
            printf("你选择的日期共有%d趟飞机,请输入你要购买的班次(1~%d):", p->n, p->n);
            int id;
            scanf("%d", &id);
            fNode *q = p->fl->after;
            while (q != p->fl)
            {
                if (q->data.id == id)
                {
                    if (q->data.leftTable == 0) // 没票了
                    {
                        for (int i = 0; i < 10; i++)
                            printf("*");
                        printf("\e[31m该班次航班没票了!购买失败!\e[0m");
                        for (int i = 0; i < 10; i++)
                            printf("*");
                        putchar('\n');
                        return;
                    }
                    else if (q->data.isFly == 'Y') // 起飞了
                    {
                        for (int i = 0; i < 10; i++)
                            printf("*");
                        printf("\e[31m该趟航班已经起飞了!购买失败!\e[0m");
                        for (int i = 0; i < 10; i++)
                            printf("*");
                        putchar('\n');
                        return;
                    }
                    else // 购买成功
                    {
                        q->data.leftTable--; // 票数减一
                        strcpy(rl->tickets[rl->num].time, time);
                        rl->tickets[rl->num].id = id;
                        rl->num++; // 写入购票记录
                        puts("\e[32m购买成功!\e[0m");
                        print_flight(q);
                        return;
                    }
                }
                q = q->after;
            }
        }
        p = p->next;
    }
    for (int i = 0; i < 10; i++)
        printf("*");
    printf("\e[31m仅可购买今天和未来十天的机票!!!购买失败!!!\e[0m"); // 没有找到日期
    for (int i = 0; i < 10; i++)
        printf("*");
    putchar('\n');
    return;
}

void return_ticket(dList dl, record *rl)
{
    printf("请输入你要退票的日期:");
    char time[MAX];
    scanf("%s", time);
    dNode *p = dl->next;
    while (p != NULL)
    {
        if (!strcmp(p->time, time))
        {
            printf("你选择的日期共有%d趟飞机,请输入你要退票的班次(1~%d):", p->n, p->n);
            int id;
            scanf("%d", &id);
            fNode *q = p->fl->after;
            while (q != p->fl)
            {
                if (q->data.id == id) // 找到了
                {
                    for (int i = 0; i < rl->num; i++) // 判断是否购买过这趟航班
                    {
                        if (!strcmp(rl->tickets[i].time, time) && rl->tickets[i].id == id) // 购买过
                        {
                            if (q->data.isFly == 'Y') // 起飞了
                            {
                                for (int j = 0; j < 10; j++)
                                    printf("*");
                                printf("\e[31m该趟航班已经起飞了!退票失败!\e[0m");
                                for (int j = 0; j < 10; j++)
                                    printf("*");
                                putchar('\n');
                                return;
                            }
                            else // 还没起飞
                            {
                                q->data.leftTable++; // 余票加一
                                for (int j = i; j < rl->num - 1; j++)
                                {
                                    rl->tickets[j] = rl->tickets[j + 1]; // 删除记录
                                }
                                rl->num--;
                                puts("\e[31m退票成功!\e[0m");
                                return;
                            }
                        }
                    }
                    for (int i = 0; i < 10; i++)
                        printf("*");
                    printf("\e[31m你没有购买过这趟航班!退票失败!\e[0m");
                    for (int i = 0; i < 10; i++)
                        printf("*");
                    putchar('\n');
                    return;
                }
                q = q->after;
            }
        }
        p = p->next;
    }
    for (int i = 0; i < 10; i++)
        printf("*");
    printf("\e[31m仅可以提前十天退订机票!!!\e[0m"); // 没有找到日期
    for (int i = 0; i < 10; i++)
        printf("*");
    putchar('\n');
    return;
}

void my_tickets(dList dl, record *rl)
{
    for (int i = 0; i < 50; i++)
        printf("-");
    printf("\e[32m个人中心\e[0m");
    for (int i = 0; i < 50; i++)
        printf("-");
    putchar('\n');
    if (rl->num == 0) // 没有票
    {
        puts("\e[31m你购买的票数为零,欢迎你去购买机票!\e[0m");
        return;
    }
    printf("尊敬的王星兴先生,你总共购买了%d张机票!\n\n", rl->num);
    puts("日期\t\t班次\t航班名字\t机型\t起点\t起飞时间\t终点\t到达时间\t飞行时间\t票价");
    int sum = 0;                      // 机票钱
    for (int i = 0; i < rl->num; i++) // 有票
    {
        dNode *p = dl->next;
        while (p != NULL) // 遍历天节点
        {
            if (!strcmp(p->time, rl->tickets[i].time)) // 找到这一天
            {
                fNode *q = p->fl->after;
                while (q != p->fl) // 遍历航班班次
                {
                    if (q->data.id == rl->tickets[i].id) // 找到这个航班
                    {
                        sum += q->data.value;
                        printf("%s\t", p->time);
                        printf("%d\t%s\t%s\t", q->data.id, q->data.flightName, q->data.flightType);
                        printf("%s\t%s\t\t%s\t", q->data.startCity, q->data.startTime, q->data.arriveCity);
                        printf("%s\t\t%s\t$%d\n", q->data.arriveTime, q->data.flyTime, q->data.value);
                    }
                    q = q->after;
                }
            }
            p = p->next;
        }
    }
    printf("\e[31m\n共计花费:$%d\n\e[0m", sum);
    return;
}

void init_record(record **rl)
{
    *rl = (record *)malloc(sizeof(record));
    (*rl)->num = 0;
}

void sort_dlist(dList dl)
{
    printf("请选择排序方式(1.按起飞时间 2.按起点站首字母 3.按终点站首字母):");
    int num;
    scanf("%d", &num);
    if (num == 2)
    {
        for (int i = 0; i < 15; i++)
            printf("*");
        printf("\e[31m资金不足!该功能暂未实现\e[0m"); // 没有找到日期
        for (int i = 0; i < 15; i++)
            printf("*");
        putchar('\n');
        return;
    }
    if (num == 3)
    {
        for (int i = 0; i < 15; i++)
            printf("*");
        printf("\e[31m资金不足!该功能暂未实现\e[0m"); // 没有找到日期
        for (int i = 0; i < 15; i++)
            printf("*");
        putchar('\n');
        return;
    }
    if (num == 1)
    {
        puts("按起飞时间排序");
        dNode *p = dl->next;
        while (p != NULL)
        {
            for (int i = 0; i < p->n - 1; i++) // 冒泡排序
            {
                fNode *q = p->fl->after;               // 每趟从头开始遍历
                for (int j = 0; j < p->n - 1 - i; j++) // 按起飞时间排序
                {
                    if (strcmp(q->data.startTime, q->after->data.startTime) > 0) // 从早到晚
                    {
                        flight_t temp;
                        temp = q->data;
                        q->data = q->after->data;
                        q->after->data = temp;
                    }
                    q = q->after;
                }
            }
            p = p->next;
        }
        puts("\e[32m排序完成!\n\e[0m");
        print_dlist(dl);
        return;
    }
}